﻿/*
	[ru]	Пример создания нескольких инстанций движка.
*/


#include "Engine.h"
using namespace Engine;



class CExample : public ICoreEventListener
{
private:
	CBaseProgramShellPtr	pProgram;
	float					fLastTime;

public:
	CExample(): fLastTime(0)
	{
	}

	~CExample()
	{
	}
	
	void Draw();
	void Process();

	virtual void OnInit();
	virtual void OnFree();

	virtual void OnUpdate();

	virtual void Release()									{ delete this; }
	virtual e_win_event::type GetEvents()					{ return e_win_event::UNKNOWN; }

	virtual void ProcessMessage(const TWindowEvent &sEvent)	{}
	virtual void OnException()								{}
	
	static uint CALLBACK s_RunEngine(void *pParam);
};




inline void CExample::Draw()
{
	RENDERGL()->ClearBuffers();

	pProgram->Bind();
	RENDERGL()->DrawFSQuad();

	RENDERGL()->SwapBuffers();
}


inline void CExample::Process()
{
	INPUT()->Update();

	if ( INPUT()->IsKey(e_key::ESCAPE) )
		CORE()->QuitEngine();

	INPUT()->Reset();
}


void CExample::OnInit()
{
	bool	ret = true;

	static const char *	s_aShaders[] = {
		"shared/fractal.prg",
		"shared/fractal2.prg"
	};

	const char *	p_prog_file = s_aShaders[ CORE()->GetInstanceId() % COUNT_OF(s_aShaders) ];

	ret &= RESMAN()->Load( e_resource::PROGRAM_SHELL, pProgram, p_prog_file );

	MSTACK()->SetMatrix( mat4::BuildOrtho2D( frect(-1.f, -1.f, 1.f, 1.f) ), e_transform::PROJECTION );

	WINDOW()->AllowPause( false );

	ASSERT( ret );
}


void CExample::OnFree()
{
}


void CExample::OnUpdate()
{
	CORE()->Update();
	Draw();
	
	fLastTime += CORE()->GetUpdateTimeDelta();

	if ( fLastTime > 1.f/60.f )
	{
		fLastTime = 0.f;
		Process();
	}
}


uint CALLBACK CExample::s_RunEngine(void *pParam)
{
	CExample	*		p_example			= new CExample();
	TEngInitParams		s_init_params;
	e_log_output::bits	e_log_bits			= e_log_output::LOG_FILE_BIT
											DEBUG_ONLY( | e_log_output::MESSAGE_BIT )
											;
	
	s_init_params.eFlags					= e_eng_init_flags::OPENGL_4_2
											| e_eng_init_flags::CORE_PROFILE
											| e_eng_init_flags::EXTENDED_CONTEXT
											//| e_eng_init_flags::DEBUG_MODE
											//| e_eng_init_flags::STREAMED_LOAD
											//| e_eng_init_flags::STEREO
											//| e_eng_init_flags::ES2_PROFILE
											;
	s_init_params.sApplicationName			= "Multi Engine Instances Sample";
	s_init_params.sClassName				= "";
	s_init_params.pHandle					= nullptr;
	s_init_params.pIcon						= nullptr;

	s_init_params.sAudioParams.sAudioDevice	= "";

	s_init_params.sRenInit.uColorDepth		= 32;
	s_init_params.sRenInit.uZBufferDepth	= 24;
	s_init_params.sRenInit.uStencilDepth	= 0;
	s_init_params.sRenInit.uColorSamples	= 0;
	s_init_params.sRenInit.uCSAASamples		= 0;
	s_init_params.sRenInit.uMSAASamples		= 0;
	s_init_params.sRenInit.uPixelFormat		= 0;

	s_init_params.sRenParams.bFullScreen	= false;
	s_init_params.sRenParams.bVSync			= false;
	s_init_params.sRenParams.eMode			= e_window_mode::ALLOW_SIZING;
	s_init_params.sRenParams.sWinPos		= ((ivec3 *)pParam)->xy();
	s_init_params.sRenParams.sWinSize		= ivec2( 640, 480 );
	
	s_init_params.sExtParams.uLogLevel		= 15;
	s_init_params.sExtParams.eLogFilter		= e_log_msg::FILTER_ALL;
	s_init_params.sExtParams.eResManFlags	= e_resman_flags::FREE_NON_REF | e_resman_flags::SET_DEFAUL_RES;
	s_init_params.sExtParams.sResDirectory	= "data";
	s_init_params.uLoadThreads				= 0;
	s_init_params.uRenderThreads			= 0;
	
	if ( !RunEngine( p_example, s_init_params, e_log_bits, "log.html", nullptr ) )
		return 1;

	return 0;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	TThread		s_thread1,
				s_thread2,
				s_thread3,
				s_thread4,
				s_thread5,
				s_thread6;
	ivec3		v_pos1( -5,		0, 0 ),
				v_pos2( 645,	0, 0 ),
				v_pos3( 1295,	0, 0 ),
				v_pos4( -5,	  520, 0 ),
				v_pos5( 645,  520, 0 ),
				v_pos6( 1295, 520, 0 );

	s_thread1.Create( &CExample::s_RunEngine, &v_pos1, false );
	Sleep(2000);

	s_thread2.Create( &CExample::s_RunEngine, &v_pos2, false );
	Sleep(2000);

	s_thread3.Create( &CExample::s_RunEngine, &v_pos3, false );
	Sleep(2000);

	s_thread4.Create( &CExample::s_RunEngine, &v_pos4, false );
	Sleep(2000);

	s_thread5.Create( &CExample::s_RunEngine, &v_pos5, false );
	Sleep(2000);

	s_thread6.Create( &CExample::s_RunEngine, &v_pos6, false );
	Sleep(2000);

	s_thread1.Wait();
	s_thread2.Wait();
	s_thread3.Wait();
	s_thread4.Wait();
	s_thread5.Wait();
	s_thread6.Wait();

	return 0;
}